package com.snow.common.exception;

import com.snow.common.base.R;
import com.snow.common.base.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Auther: yanke
 * @Date: 2018/10/10 0010 09:44
 * @Description:
 */
@Slf4j
@RestControllerAdvice
public class ExceptionController implements InitializingBean {

    private Map<String, ResponseCode> errorCodeMap = new HashMap<>();

  /*  // 捕捉token的异常
    @ExceptionHandler(TokenException.class)
    public R token(TokenException e) {
        return new R(ResponseCode.UNAUTHORIZED, e.getMsg());
    }

    // 捕捉shiro的异常
    @ExceptionHandler(ShiroException.class)
    public R handle401(ShiroException e) {
        return new R(ResponseCode.UNAUTHORIZED, "权限错误");
    }

    // 捕捉UnauthorizedException
    @ExceptionHandler(UnauthorizedException.class)
    public R handle401() {
        return new R(ResponseCode.UNAUTHORIZED, "shiro错误");
    }*/

    // 捕捉ConstraintViolationException,--------hibernate validator数据校验   ,不知道为什么突然失效了
    @ExceptionHandler(ConstraintViolationException.class)
    public R constraintViolationException(ConstraintViolationException e) {
        if (e instanceof ConstraintViolationException) {
            ConstraintViolationException exs = (ConstraintViolationException) e;
            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
                return new R(ResponseCode.NOT_ACCEPTABLE_406, item.getMessage());
            }
        }
        return new R(ResponseCode.NOT_ACCEPTABLE_406, e.getMessage());
    }

    // 捕捉 hibernate validator数据校验
    @ExceptionHandler(BindException.class)
    public R bindException(BindException e) {
        String errorMessage = null;
        if (e instanceof BindException) {
            BindingResult bindingResult = e.getBindingResult();
            List<ObjectError> allErrors = bindingResult.getAllErrors();
            for (ObjectError allError : allErrors) {
                errorMessage = allError.getDefaultMessage();
            }
        }
        return new R(ResponseCode.NOT_ACCEPTABLE_406, errorMessage);
    }

    // 捕捉 hibernate validator数据校验
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R businessException(MethodArgumentNotValidException e) {
        String errorMessage = null;
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        for (ObjectError allError : allErrors) {
            errorMessage = allError.getDefaultMessage();
        }
        return new R(ResponseCode.NOT_ACCEPTABLE_406, errorMessage);
    }

    //断言异常
    @ExceptionHandler(IllegalArgumentException.class)
    public R IllegalArgumentException(IllegalArgumentException e) {
        ResponseCode responseCode = null;
        if (e instanceof IllegalArgumentException) {
            IllegalArgumentException exs = (IllegalArgumentException) e;
            responseCode = errorCodeMap.get(exs.getMessage());
        }
        return new R(responseCode, responseCode.getDesc());
    }

    // 捕捉BusinessException
    @ExceptionHandler(BadRequestException.class)
    public R businessException(BadRequestException businessException) {
        return new R(ResponseCode.BUSINESSEXCEPTION_1001, businessException.getMsg());
    }

    // 捕捉MaxUploadSizeExceededException文件上传大小超出
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public R businessException(MaxUploadSizeExceededException b) {
        return new R(ResponseCode.BUSINESSEXCEPTION_1001, "上传文件大小超出");
    }

    // 捕捉其他所有异常
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(Exception.class)
    public R globalException(Exception exception, HttpServletRequest request, Throwable ex) {
        log.error(exception.getMessage());
//        log.error("异常用户id:" + SubjectUtils.getUserId() + "--------" + new Date());
//        log.error("异常请求接口" + ContextHolderUtils.getRequest().getRequestURL());
        exception.printStackTrace();
        log.error(ex.getMessage());
        ex.printStackTrace();
        return new R(ResponseCode.INTERNAL_SERVER_ERROR_500, "服务器忙,请稍后再试");
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

    @Override
    public void afterPropertiesSet() {
        ResponseCode[] values = ResponseCode.values();
        Map map = new HashMap();
        for (ResponseCode responseCode : values) {
            map.put(responseCode.getCode(), responseCode);
        }
        errorCodeMap.putAll(map);
    }
}
